import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Vector;

import jp.co.csk.vdm.toolbox.VDM.CGException;

public class Parser {
	public HashSet<State> stateSet = new HashSet<State>();
	public String inicial = null;
	public UML uml;
	public boolean flag = false;

	public void parseUML(String umlString) {

		try {
			uml = new UML();
		} catch (CGException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		String[] subs = umlString.split("\n");
		for (int a = 0; a != subs.length; a++) {
			parseRelation(subs[a]);

		}

		try {
			uml.addStartState(uml.getState(inicial));
			flag = true;
		} catch (CGException e) {
			flag = false;
			System.out.println("Invalid\n");
			
		}

		System.out.println();
	}

	private void parseRelation(String string) {

		String[] subs = string.split("-");

		if (subs.length != 3) {
			System.out.println("Bad Syntax on UML line: " + string);
			flag = false ;
		} else {

			State q1, q2;
			try {
				if (inicial == null) {
					inicial = subs[0];
				}

				if (uml.stateExists(subs[0])) {
					q1 = uml.getState(subs[0]);
				} else {
					q1 = new State(subs[0]);
				}

				if (uml.stateExists(subs[2])) {
					q2 = uml.getState(subs[2]);
				} else {
					q2 = new State(subs[2]);
				}

				Transition t1 = new Transition(subs[1], q1, q2);
				q1.addTransition(t1);

				uml.addState(q1);
				uml.addState(q2);

			} catch (CGException e) {
				// TODO Auto-generated catch block
				flag = false;
				System.out.println("Invalid relation \n");
			}

		}
	}

	public void parseTraces(String trace) {

		String[] subs = trace.split("\n");
		for (int a = 0; a != subs.length; a++) {
			parseTrace(subs[a]);
		}

	}

	private void parseTrace(String trace) {
		Vector<State> vec = new Vector<State>();
		try {
			String[] subs = trace.split(",");

			for (int a = 0; a != subs.length; a++) {

				vec.add(uml.getState(subs[a]));

			}

			if (uml.verifyPath(vec)) {
				System.out.println("Trace " + trace
						+ " was found in the UML \n");
			} else {
				System.out.println("Trace " + trace
						+ " was NOT found in the UML \n");
			}

		} catch (Exception e) {
			// TODO Auto-generated catch block
			System.out
					.println("Trace "
							+ trace
							+ " was NOT found in the UML, because it's an invalid Trace \n");

		}
	}

	public void readFromFile(String filename, int b) {

		String returnValue = "";
		FileReader file = null;

		try {
			file = new FileReader(filename);
			BufferedReader reader = new BufferedReader(file);
			String line = "";
			while ((line = reader.readLine()) != null) {
				returnValue += line + "\n";
			}
			reader.close();
		} catch (FileNotFoundException e) {
			throw new RuntimeException("File not found");
		} catch (IOException e) {
			throw new RuntimeException("IO Error occured");
		} finally {
			if (file != null) {
				try {
					file.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		if (b == 1) {
			parseUML(returnValue);
		}
		if (b == 2) {
			parseTraces(returnValue);
		}
	}

	public void menu() {

		System.out.println("\t\t WELCOME \n");
		while (true) {
			System.out.println("- - - - - - - - - - - - - - - - - - - - - - -");
			System.out.println("Please pick one of the following options ");
			System.out.println("1 - Load a State UML from a file ");
			if (flag == true) {
				System.out.println("2 - Test a Trace from a file ");

				System.out.println("3 - Input a Trace via console ");
			}
			System.out.println("0 - Exit ");
			System.out.print(">> ");

			Scanner reader;
			reader = new Scanner(System.in);

			String option = reader.nextLine();
			try {

				int a = Integer.parseInt(option);

				switch (a) {
				case 1:
					System.out
							.println("Insira o nome do ficheiro (p/e 'uml.txt') que esteja no directorio testJava ");
					System.out.print(">> ");
					option = reader.nextLine();
					readFromFile("testJava\\" + option, 1);
					break;
				case 2:
					if (flag == true) {
						System.out
								.println("Insira o nome do ficheiro (p/e 'trace.txt') que esteja no directorio testJava ");
						System.out.print(">> ");
						option = reader.nextLine();

						readFromFile("testJava\\" + option, 2);
						break;
					}
					System.out.println("Invalid \n");
					break;
				case 3:
					if (flag == true) {
						System.out.println("Insira um trace com os estados separados por uma virgula \n");
						System.out.print(">> ");
						option = reader.nextLine();
						parseTrace(option);
						break;
					}
					System.out.println("Invalid \n");
					break;
				case 0:
					System.exit(0);
				default:
					System.out.println("Nobody here but us chickens");
					break;

				}
			} catch (Exception e) {
				System.out.println("Invalid \n");
			}
		}
	}
}
